package com.xiaoluo.service;

import com.xiaoluo.cd.dao.JobsMapper;
import com.xiaoluo.cd.entity.base.*;
import com.xiaoluo.common.enums.JobModeEnum;
import com.xiaoluo.common.enums.JobStatusEnum;
import com.xiaoluo.common.enums.JobTypeEnum;
import com.xiaoluo.common.queue.BuildLogMap;
import com.xiaoluo.common.queue.JobQueue;
import com.xiaoluo.common.utils.ApplicationContextUtils;
import com.xiaoluo.common.utils.JsonUtils;
import com.xiaoluo.common.utils.Shell;
import com.xiaoluo.web.form.GitCommit;
import com.xiaoluo.web.form.JobForm;
import com.xiaoluo.web.form.ProjectForm;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Project : XL-CD
 * Package : com.xiaoluo.service
 * Created by Willian.
 * Date  : 2016/1/6 16:56.
 */
@Service
@Transactional
public class JobService {

    private final static Logger logger = LoggerFactory.getLogger(JobService.class);

    @Autowired
    private JobsMapper jobsMapper;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private VersionService versionService;

    /**
     * 保存job
     * @param jobs
     */
    public void save(Jobs jobs){
        jobsMapper.insert(jobs);
    }

    /**
     *
     * @param id
     * @return
     */
    public Jobs get(Long id){
        return jobsMapper.selectByPrimaryKey(id);
    }

    /**
     *
     * @param pId
     * @param type
     * @return
     */
    public Jobs get(Long pId,byte type){
        JobsExample example = new JobsExample();
        example.createCriteria().andPidEqualTo(pId).andJobTypeEqualTo(type);
        List<Jobs> list = jobsMapper.selectByExampleWithBLOBs(example);

        if(list != null && list.size() >0){
            return list.get(0);
        }
        return null;
    }

    /**
     *
     * @param jobName
     * @return
     */
    public Jobs get(String jobName){
        JobsExample example = new JobsExample();
        example.createCriteria().andJobNameEqualTo(jobName);
        List<Jobs> list = jobsMapper.selectByExampleWithBLOBs(example);

        if(list != null && list.size() >0){
            return list.get(0);
        }
        return null;
    }
    public List<Jobs> getChildren(Long pId){
        JobsExample example = new JobsExample();
        example.createCriteria().andPidEqualTo(pId);
        List<Jobs> list = jobsMapper.selectByExampleWithBLOBs(example);

        return list;
    }

    /**
     *
     * @param jobName
     * @param type
     * @return
     */
    public Jobs get(String jobName,byte type){
        JobsExample example = new JobsExample();
        example.createCriteria().andJobNameEqualTo(jobName).andJobTypeEqualTo(type);
        List<Jobs> list = jobsMapper.selectByExample(example);

        if(list != null && list.size() >0){
            return list.get(0);
        }
        return null;
    }
    /**
     *
     * @param id
     * @param type
     * @return
     */
    public boolean isExist(Long id,Integer type){
        JobsExample example = new JobsExample();
        example.createCriteria().andPidEqualTo(id).andJobTypeEqualTo(type.byteValue());
        List<Jobs> list = jobsMapper.selectByExample(example);

        if(list != null && list.size() >0){
            return true;
        }
        return false;
    }

    /**
     *
     * @param projects
     * @param parentJobId
     * @param typeEnum
     */
    public void submit(Projects projects,Long parentJobId,JobTypeEnum typeEnum,JobModeEnum mode){
        Jobs parentJobs = get(parentJobId);
        Jobs jobs = new Jobs();
        jobs.setJobType(typeEnum.getValue());
        jobs.setJobStatus(JobStatusEnum.RUN.getValue());
        jobs.setJobMode(mode.getValue());
        jobs.setJobName(parentJobs.getJobName());
        jobs.setProjId(projects.getId());
        jobs.setPid(parentJobId);
        jobs.setCreateAt(new Date());
        jobs.setVersionName(parentJobs.getVersionName());
        jobs.setVersionId(parentJobs.getVersionId());
        jobs.setCommitDate(parentJobs.getCommitDate());
        jobs.setCommitName(parentJobs.getCommitName());
        save(jobs);
        //提交任务
        JobQueue.push(jobs);
    }

    /**
     *
     * @param jobs
     */
    public void submit(Jobs jobs){
        jobs.setJobStatus(JobStatusEnum.RUN.getValue());
        jobs.setUpdateAt(new Date());
        jobsMapper.updateByPrimaryKey(jobs);
        //提交任务
        JobQueue.push(jobs);
    }
    /**
     *
     * @param projects
     */
    public void submit(Projects projects,Version version,JobModeEnum mode){

        String uuid = UUID.randomUUID().toString();
        Jobs jobs = new Jobs();
        jobs.setJobType(JobTypeEnum.BUILD.getValue());
        jobs.setJobStatus(JobStatusEnum.RUN.getValue());
        jobs.setJobMode(mode.getValue());
        jobs.setJobName(uuid);
        jobs.setProjId(projects.getId());
        jobs.setCreateAt(new Date());

        if(version != null){
            jobs.setCommitName(version.getVersion());
            jobs.setCommitDate(version.getCreateAt());
            jobs.setVersionId(version.getId());
            jobs.setVersionName(version.getVersion());
        }else {
            jobs.setCommitName(uuid);
            jobs.setCommitDate(new Date());
            jobs.setVersionName(version.getVersion());
            jobs.setVersionId(0l);
        }

        save(jobs);
        //提交任务
        JobQueue.push(jobs);
    }
    /**
     *
     * @param obj
     */
    public void runJob(Jobs obj){
        ProjectForm projects = projectService.findById(obj.getProjId());
        Version version = versionService.getVersion(obj.getVersionId());

        Jobs temp = get(obj.getJobName(),obj.getJobType());
        /**
         *
         */
        temp.setJobMode(obj.getJobMode());

        if(projects.getScript() != null && !"".equals(projects.getScript())){
            switch (obj.getJobType()){
                case 0:
                    Shell.build(projects,version,temp,"build");
                    break;
                case 1:
                    Shell.build(projects,version, temp, "test");
                    break;
                case 2:
                    Shell.build(projects,version, temp, "deploy");
                    break;
            }
        }else {
            temp.setJobStatus(JobStatusEnum.ERROR.getValue());
            temp.setJobDesc("no script.");
        }
        /**
         * updae parent Job status.
        if(parentJobs != null){
            parentJobs.setJobStatus(temp.getJobStatus());
            parentJobs.setJobType(temp.getJobType());
            jobsMapper.updateByPrimaryKey(parentJobs);
        }
         */

        jobsMapper.updateByPrimaryKeyWithBLOBs(temp);
        /**
         * clean log map.
         */
        BuildLogMap.remove(temp.getJobName() + "_" + temp.getJobType());
    }


    /**
     *
     * @param versionId
     * @param type
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public List<JobForm> list(Long versionId,Integer type,Integer pageIndex,Integer pageSize,String commitName){
        List<JobForm> result = new ArrayList<JobForm>();


        JobsExample example = new JobsExample();
        JobsExample.Criteria criteria = example.createCriteria();
        criteria.andVersionIdEqualTo(versionId).andPidIsNull();
        if(commitName != null && !"".equals(commitName)){
            criteria.andCommitNameEqualTo(commitName);
        }
        example.setLimit(pageSize);
        example.setOffset(pageIndex);

        example.setOrderByClause("id desc");

        //Integer count = jobsMapper.countByExample(example);
        List<Jobs> list = jobsMapper.selectByExample(example);

        if(list != null && list.size() >0){
            for(Jobs job:list){
                JobForm jobForm = new JobForm();
                BeanUtils.copyProperties(job,jobForm);
                jobForm.setBuildStatus(job.getJobStatus());

                List<Jobs> children = getChildren(job.getId());
                if(children != null && children.size() >0){
                    for (Jobs c:children){
                        if(JobTypeEnum.TEST.getValue() == c.getJobType()){
                            jobForm.setTestStatus(c.getJobStatus());
                        }else if(JobTypeEnum.DEPLOY.getValue() == c.getJobType()){
                            jobForm.setDeployStatus(c.getJobStatus());
                        }
                    }
                }
                //
                result.add(jobForm);
            }
        }
        return result;
    }

    /**
     * 获取上周的job列表
     * @return
     */
    @Scheduled(cron="0 0 1 * * *")
    public void cleanJob(){
        logger.info("start clean job.");
        JobsExample example = new JobsExample();
        String expire = ApplicationContextUtils.propertyConfigurer.getProperty("xl.cd.expire").toString();
        int expireDate = Integer.parseInt(expire);

        Date now  = new Date();
        Date st = DateUtils.addDays(now,-expireDate);
        Date end = DateUtils.addDays(now,-expireDate*2);
        logger.info("start Date:{},end Date:{}",st,end);

        example.createCriteria().andCreateAtLessThan(st).andCreateAtGreaterThan(end);
        List<Jobs> list = jobsMapper.selectByExample(example);

        if(list != null && list.size() >0){
            for(Jobs job : list){
                Projects projects = projectService.get(job.getProjId());
                Shell.clean(projects, job);
            }
        }
    }
}
